package main
import (
	"fmt"
)

//  11. 数组和切片
func main(){
	var a [3]int
	a[0] = 12
	a[2] = 22

	fmt.Println("a=",a)

	a1 := [3]int {12, 1253, 41}
	a2 := [3]int {12}
	fmt.Println("a1=",a1)
	fmt.Println("a2=",a2)

	// 忽略长度
	aa3 := [...]int{12,0,7}
	fmt.Println("aa3=",aa3)

	// 数组的大小是类型的一部分
	// aa4 := [3]int{12, 45, 78}
	// var bb4 [5]int
	// bb4 = aa4	//不可以直接转 类型不一样的原因是：数组的大小是类型的一部分

	aa5 := [...]string{"aaa", "bbb", "cccc", "dddd"}
	bb5 :=aa5
	bb5[0] = "abcde"
	fmt.Println("aa5 =", aa5)
	fmt.Println("bb5 =", bb5)

	// 数组长度
	aa6 := [...]float64{12.3, 45.6, 78.96}
	fmt.Println("length of aa6 is", len(aa6))

	// 迭代数组
	for i := 0; i < len(aa6); i++ {
		fmt.Printf("%d th element f a is %.5f\n", i, aa6[i]) //.5 是保存五位小数
	}
	fmt.Println()

	// range 
	for i,v := range aa6{
		fmt.Printf("%d th element f a is %.5f\n", i, v) //.5 是保存五位小数
	}

	// 多维数组
	arr7 := [3][2]string{
		{"11", "12"},
		{"22", "23"},
		{"33", "34"},
	}
	fmt.Println("arr7", arr7)
	printarray(arr7)
	var arr8 [3][2]string
	arr8[0][0] = "yang1"
	arr8[0][1] = "yang2"
	arr8[1][0] = "yang3"
	arr8[1][1] = "yang4"
	arr8[2][0] = "yang5"
	arr8[2][1] = "yang6"
	printarray(arr8)

	// 切片 切片是由数组建立的一种方便、灵活且功能强大的包装（Wrapper）。切片本身不拥有任何数据。它们只是对现有数组的引用。
	arr9 := [5]int{1,2,3,4,5}
	var  brr9 []int = arr9[2:4]	//下标2开始 到下标为4结束 不包括4
	brr9[0] = 123	//切片的数据 进行修改后 一样修改到原来的数据的
	fmt.Println("arr9=", arr9)
	fmt.Println("brr9=", brr9)
	//切片的数据 进行修改后 一样修改到原来的数据的
	darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
    dslice := darr[2:5]
	fmt.Println("array before", darr)
	for i := range dslice {
		dslice[i]++
	}
	fmt.Println("array before", darr)
	//当多个切片共用相同的底层数组时，每个切片所做的更改将反映在数组中。
	numa := [3]int{78, 79 ,80}
    nums1 := numa[:] // 切片所有的数据都传过去
    nums2 := numa[:]
    fmt.Println("\narray before change 1", numa)
    nums1[0] = 100
    fmt.Println("array after modification to slice nums1", numa)
    nums2[1] = 101
    fmt.Println("array after modification to slice nums2", numa)

	// 切片的长度和容量
	fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    fmt.Printf("\nlength of slice %d capacity %d\n", len(fruitslice), cap(fruitslice)) // length of is 2 and capacity is 6
    fruitslice = fruitslice[:cap(fruitslice)] // re-slicing furitslice till its capacity
    fmt.Println("After re-slicing length is",len(fruitslice), "and capacity is",cap(fruitslice))

	// 使用 make 创建一个切片
	make1 := make([]int, 5, 5)
	fmt.Println("\nmake1", make1)
	// append 追加切片元素 
	cars := []string{"Ferrari", "Honda", "Ford"}
    fmt.Println("cars:", cars, "has old length", len(cars), "and capacity", cap(cars)) // capacity of cars is 3
    cars = append(cars, "Toyota")
    fmt.Println("cars:", cars, "has new length", len(cars), "and capacity", cap(cars)) // capacity of cars is doubled to 6
	
	var names []string
	if names == nil {
		names = append(names, "John", "Sebastian", "Vinay", "Vinay")
        fmt.Println("names contents:",names)
	}
	// 也可以使用 ... 运算符将一个切片添加到另一个切片
	veggies := []string{"potatoes", "tomatoes", "brinjal"}
    fruits := []string{"oranges", "apples"}
    food := append(veggies, fruits...)
    fmt.Println("\nfood:",food)

	nos := []int{8, 7, 6}
    fmt.Println("slice before function call", nos)
    subtactOne(nos)                               // function modifies the slice
    fmt.Println("slice after function call", nos) // modifications are visible outside
	
	// 多维切片
	pls := [][]string {
		{"C", "C++"},
		{"JavaScript"},
		{"Go", "Rust"},
		}
	for _, v1 := range pls {
		for _, v2 := range v1 {
			fmt.Printf("%s ", v2)
		}
		fmt.Printf("\n")
	}

	// 内存优化
	countriesNeeded := countries()
    fmt.Println("\n", countriesNeeded)
}



func printarray(a [3][2]string) {
	for _, v1 := range a {
		for _, v2 := range v1 {
			fmt.Printf("%s ", v2)
		}
		fmt.Printf("\n")
	}
}

func subtactOne(numbers []int) {
	for i := range numbers {	//会改变传过来的值的本身的数据
		numbers[i] -= 2
	}
}


// 内存优化
func countries() []string {
    countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}
    neededCountries := countries[:len(countries)-2]
    countriesCpy := make([]string, len(neededCountries))
    copy(countriesCpy, neededCountries) //copies neededCountries to countriesCpy
    return countriesCpy
}
